/* 
 * Copyright 2011-2012 Andrew Brock
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.catchwa.myvideobrowser;

import java.awt.Desktop;
import org.catchwa.myvideobrowser.model.Movie;
import org.catchwa.myvideobrowser.model.AlternateMatch;
import org.catchwa.myvideobrowser.db.DatabaseFacade;
import org.catchwa.myvideobrowser.db.SqliteDatabase;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.Manifest;
import javax.swing.JFileChooser;
import javax.swing.UIManager;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.catchwa.myvideobrowser.api.TheMovieDbApi;
import org.catchwa.myvideobrowser.gui.Browser;

/**
 *
 * @author Andrew Brock
 */
public class Main {

  private static Logger log = Logger.getLogger(Main.class);
  private static Browser browser;
  public static DatabaseFacade db;
  private static PropertiesConfiguration properties;

  public static void main(String[] args) {
    PropertyConfigurator.configure(Main.class.getClassLoader().getResource("log4j.properties"));
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e) {
      log.error("Error setting the Swing L&F", e);
    }
    
    try {
    javax.swing.SwingUtilities.invokeAndWait(new Runnable() {

      @Override
      public void run() {
        browser = new Browser();
      }
    });
    } catch (InterruptedException e)
    {
      log.error("Interrupted whilst creating browser", e);
    } catch (InvocationTargetException e){
      log.error("Error whilst creating browser, e");
    }
    
    db = new SqliteDatabase();

    File mvbSettingsDir = new File(System.getenv("APPDATA") + "\\MyVideoBrowser");
    if (!mvbSettingsDir.exists()) {
      mvbSettingsDir.mkdir();
    }
    File mvbSettings = new File(mvbSettingsDir.getAbsolutePath() + "\\config.properties");
    if(! mvbSettings.exists()){
      try {
          FileUtils.copyFile(new File(Main.class.getClassLoader().getResource("config.properties").getFile()), mvbSettings);
      } catch (IOException e)
      {
        log.error("Error copying the properties file", e);
      }
    }
    try {
      properties = new PropertiesConfiguration(mvbSettings);
    } catch (ConfigurationException e) {
      log.error("Error loading the properties file", e);
    }
    properties.setAutoSave(true);
    
    String rootDirectory = properties.getString("root.directory");
    if (rootDirectory == null || !new File(rootDirectory).exists()) {
      boolean chosen = displayRootDirectoryChooser();
      if (!chosen) {
        System.exit(0);
      }
    }

    ArrayList<File> existing = new ArrayList<File>();
    List<Movie> movies = db.getAll();
    for (Movie m : movies) {
      existing.add(m.getFile());
      browser.addMovieToTable(m);
    }

    MovieScanner.Result results = MovieScanner.scan(new File(properties.getString("root.directory")), movies);

    if (results.getMoviesToRemove() != null) {
      for (Movie m : results.getMoviesToRemove()) {
        db.remove(m);
        browser.removeMovieFromTable(m);
      }
    }

    List<File> moviesToQuery = results.getFilesToSubmit();
    TheMovieDbApi tmdb = new TheMovieDbApi();

    for (File f : moviesToQuery) {
      Movie m = tmdb.getMovieFromFile(f, null);
      if (m != null) {
        db.add(m);
        browser.addMovieToTable(m);
      }
    }
  }

  /**
   *
   * @return true if root directory was chosen
   */
  public static boolean displayRootDirectoryChooser() {
    JFileChooser chooser = new JFileChooser();
    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    chooser.setDialogTitle("Select root directory to scan for movies");
    chooser.setMultiSelectionEnabled(false);
    int choice = chooser.showOpenDialog(browser);
    if (choice == JFileChooser.APPROVE_OPTION) {
      properties.setProperty("root.directory", chooser.getSelectedFile().getAbsolutePath());
      db.flush();
      db.init();
      browser.removeAllMoviesFromTable();
      return true;
    }
    return false;
  }

  public static PropertiesConfiguration getProperties() {
    return properties;
  }

  public static DatabaseFacade getDatabase() {
    return db;
  }
  
  public static Browser getBrowser() {
    return browser;
  }
  
  public static Runnable createSwitchMovieThread(final Movie movie, final AlternateMatch alternate) {
    Runnable runnable = new Runnable() {

      @Override
      public void run() {
        browser.removeMovieFromTable(movie);
        db.remove(movie);
        TheMovieDbApi tmdb = new TheMovieDbApi();
        Movie m = tmdb.getMovieFromFile(movie.getFile(), alternate.getTmdbId());
        db.add(m);
        browser.addMovieToTable(m);
        browser.clearSelection();
      }
    };
    return runnable;
  }

  public static Runnable createOpenMovieThread(final Movie m) {
    Runnable runnable = new Runnable() {

      @Override
      public void run() {
        File f = m.getFile();
        File[] files = null;
        if (f.isDirectory()) {
          files = f.listFiles(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
              if (isVideoFile(new File(dir.getAbsolutePath() + "/" + name))) {
                return true;
              }
              return false;
            }
          });
          Arrays.sort(files);
          f = files[0];
        }
        try {
          if (f.isDirectory() && files.length > 0) {
            // If multiple video files (e.g. Part 1 & Part 2) open the directory also
            Desktop.getDesktop().open(f);
          }
          Desktop.getDesktop().open(f.getCanonicalFile());
        } catch (IOException e) {
          log.error("Error opening the video file", e);
        }
      }
    };
    return runnable;
  }

  public static boolean isVideoFile(File f) {
    if (f.isDirectory()) {
      return false;
    }
    int index = f.getName().lastIndexOf(".");
    if (index < 0) {
      return false;
    }
    List<String> extensions = Arrays.asList(properties.getStringArray("video.extensions"));
    String name = f.getName().toLowerCase();
    if (extensions.contains(name.substring(index, name.length()))) {
      return true;
    }
    return false;
  }

  public static String getVersion() {
    try {
      Class clazz = Main.class;
      String className = clazz.getSimpleName() + ".class";
      String classPath = clazz.getResource(className).toString();
      String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
      Manifest manifest = new Manifest(new URL(manifestPath).openStream());
      return manifest.getAttributes("my-video-browser").getValue("mvb-version");
    } catch (IOException e) {
      log.error("Error reading version", e);
    }
    return null;
  }
}
